package com.wlyuan.open.scanner.domain.tenant;

import com.wlyuan.open.scanner.dao.entity.CompanyDO;
import com.wlyuan.open.scanner.utils.JsonUtils;
import com.wlyuan.open.scanner.utils.UserOpenIdUtils;
import com.wlyuan.open.scanner.utils.mappings.BaseMapping;
import com.wlyuan.open.scanner.utils.mappings.MappingInvalid;
import lombok.var;
import org.mapstruct.*;
import org.mapstruct.factory.Mappers;
import org.springframework.util.CollectionUtils;

import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * @author lijing
 * @description
 */
public class TenantConvert {

    private static final Convert CONVERT = Mappers.getMapper(Convert.class);

    @Mapper(uses = {MappingInvalid.class})
    public interface Convert {

        @Mappings({
                @Mapping(target = "abbr", source = "companyShortname"),
                @Mapping(target = "englishName", source = "companyEnname"),
                @Mapping(target = "englishAbbr", source = "companyShortenname"),
                @Mapping(target = "logo", source = "companyLogo"),
                @Mapping(target = "url", source = "companyWeb"),
                @Mapping(target = "industry", source = "companyIndustry"),
                @Mapping(target = "profile", source = "companyDescription"),
                @Mapping(target = "businessLicenseUrl", source = "companyLicensepic"),
                @Mapping(target = "socialCreditCode", source = "companyLicense"),
                @Mapping(target = "provinceId", source = "companyProvinceid"),
                @Mapping(target = "cityId", source = "companyCityid"),
                @Mapping(target = "districtId", source = "companyDistrictid"),
                @Mapping(target = "address", source = "companyWorkingaddress"),
                @Mapping(target = "lat", source = "companyAddresslatitude"),
                @Mapping(target = "lon", source = "companyAddresslongitude"),
                @Mapping(target = "fax", source = "companyFax"),
                @Mapping(target = "zipcode", source = "companyZip"),
                @Mapping(target = "corporation", source = "companyMaster"),
        })
        @MappingCreation
        @BaseMapping
        CompanyTenant convert(CompanyDO source);

        @AfterMapping
        default void after(@MappingTarget CompanyTenant target, CompanyDO source) {
            target.setRaw(JsonUtils.withNullJson(source));
            Optional.ofNullable(MappingInvalid.createTenantStatus(source.getCompanyInvalid(), source.getCompanyStatus()))
                    .ifPresent(tenantInvalidEnum -> target.setStatus(tenantInvalidEnum.getValue()));
        }

        List<CompanyTenant> convert(List<CompanyDO> list);

        @Mappings({
                @Mapping(source = "companyPhone", target = "mobile"),
                @Mapping(source = "companyName", target = "driverPerson.name"),
                @Mapping(source = "idcard", target = "driverPerson.idcard"),
                @Mapping(source = "idcardBack", target = "driverPerson.idcardBack"),
                @Mapping(source = "idcardFront", target = "driverPerson.idcardFront"),
                @Mapping(source = "personFront", target = "driverPerson.personFront"),
                @Mapping(source = "birthday", target = "driverPerson.birthday"),
                @Mapping(source = "rejectReason", target = "driverPerson.rejectReason"),
                @Mapping(source = "driverPersonalSnRefuse", target = "driverPerson.status"),

                @Mapping(source = "drivingLicenseFront", target = "drivingLicense.drivingLicenseFront"),
                @Mapping(source = "vehicleFront", target = "drivingLicense.vehicleFront"),
                @Mapping(source = "plateNo", target = "drivingLicense.plateNo"),
                @Mapping(source = "vehicleType", target = "drivingLicense.vehicleType"),
                @Mapping(source = "vehicleModel", target = "drivingLicense.vehicleModel"),
                @Mapping(source = "registerDate", target = "drivingLicense.registerDate"),
                @Mapping(source = "issueDate", target = "drivingLicense.issueDate"),
                @Mapping(source = "ownerName", target = "drivingLicense.ownerName"),
                @Mapping(source = "driveringLicenseRejectReason", target = "drivingLicense.rejectReason"),
                @Mapping(source = "driverCarSnRefuse", target = "drivingLicense.status"),

                @Mapping(source = "licenseNo", target = "driverLicense.licenseNo"),
                @Mapping(source = "driverType", target = "driverLicense.driverType"),
                @Mapping(source = "driverLicenseBack", target = "driverLicense.driverLicenseBack"),
                @Mapping(source = "driverLicenseFront", target = "driverLicense.driverLicenseFront"),
                @Mapping(source = "driverIssueDate", target = "driverLicense.issueDate"),
                @Mapping(source = "driverValidFromDate", target = "driverLicense.validFromDate"),
                @Mapping(source = "driverValidToDate", target = "driverLicense.validToDate"),
                @Mapping(source = "driverOwnerName", target = "driverLicense.ownerName"),
                @Mapping(source = "driverLicenseRejectReason", target = "driverLicense.rejectReason"),
                @Mapping(source = "driverSnRefuse", target = "driverLicense.status"),

                @Mapping(source = "certNo", target = "transportCert.certNo"),
                @Mapping(source = "businessScope", target = "transportCert.businessScope"),
                @Mapping(source = "certFront", target = "transportCert.certFront"),
                @Mapping(source = "transIssueDate", target = "transportCert.issueDate"),
                @Mapping(source = "transValidToDate", target = "transportCert.validToDate"),
                @Mapping(source = "transOwnerName", target = "transportCert.ownerName"),

                @Mapping(source = "length", target = "vehicle.length"),
                @Mapping(source = "loadWeight", target = "vehicle.loadWeight"),
                @Mapping(source = "volume", target = "vehicle.volume"),
                @Mapping(source = "model", target = "vehicle.model"),
                @Mapping(source = "buyDate", target = "vehicle.buyDate"),
                @Mapping(source = "insuranceEndDate", target = "vehicle.insuranceEndDate"),
        })
        @MappingCreation
        @BaseMapping
        DriverTenant convertDriver(CompanyDO source);

        @AfterMapping
        default void after(@MappingTarget DriverTenant target, CompanyDO source) {
            target.setRaw(JsonUtils.withNullJson(source));
            Optional.ofNullable(MappingInvalid.createTenantStatus(source.getCompanyInvalid(), source.getCompanyStatus()))
                    .ifPresent(tenantInvalidEnum -> target.setStatus(tenantInvalidEnum.getValue()));
        }

        List<DriverTenant> convertDriver(List<CompanyDO> list);

        @Mappings({
                @Mapping(target = "inviterMobile", source = "source.companyPhone"),
                @Mapping(target = "inviterName", source = "source.companyName"),
                @Mapping(target = "inviterUserId", constant = "0L"),
                @Mapping(target = "inviterTenantId", source = "source.companyId"),
                @Mapping(target = "tenantId", source = "companyId"),
                @Mapping(target = "sourceKey", source = "companyId")
        })
        @BaseMapping
        InviterInfo convertInviter(CompanyDO source, Long companyId);

        @AfterMapping
        default void after(@MappingTarget InviterInfo target, CompanyDO source, Long companyId) {
            target.setRaw(JsonUtils.withNullJson(source));
        }

    }

    public static List<CompanyTenant> convert(List<CompanyDO> creation) {
        return CONVERT.convert(creation);
    }

    public static List<DriverTenant> convertDriverList(List<CompanyDO> creation) {
        List<DriverTenant> list = CONVERT.convertDriver(creation);
        if (CollectionUtils.isEmpty(list)) {
            return Collections.emptyList();
        }
        return list.stream().map(target -> {
            target.setOpenId(UserOpenIdUtils.createOpenId(target.getOpenId()));
            return target;
        }).collect(Collectors.toList());
    }

    public static CompanyTenant convert(CompanyDO creation) {
        return CONVERT.convert(creation);
    }

    public static DriverTenant convertDriver(CompanyDO creation) {
        var convert = CONVERT.convertDriver(creation);

        Optional.ofNullable(convert).ifPresent(c -> c.setOpenId(UserOpenIdUtils.createOpenId(c.getOpenId())));

        return convert;
    }

    public static InviterInfo convertInviter(CompanyDO source, Long companyId) {
        return CONVERT.convertInviter(source, companyId);
    }
}
